#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import time
import random
import threading
from datetime import datetime
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
import socket
import struct

app = Flask(__name__)
CORS(app)

# 全局数据存储
train_data = {
    "weight": {
        "a1": 0,
        "b1": 0,
        "b2": 0,
        "a2": 0
    },
    "clock": {
        "year": 2024,
        "month": 1,
        "day": 1,
        "hour": 0,
        "minute": 0,
        "second": 0
    },
    "air_consumption": {
        "driver_cab": 0.0,
        "a1": 0.0,
        "b1": 0.0,
        "b2": 0.0,
        "a2": 0.0,
        "tail_driver_cab": 0.0,
        "total": 0.0
    },
    "temp_humi": {
        "a1": {"temp": 22, "humidity": 45, "outdoor_temp": 15, "pm25": 25, "pmtovc": 30, "co2": 400},
        "b1": {"temp": 23, "humidity": 48, "outdoor_temp": 15, "pm25": 28, "pmtovc": 32, "co2": 420},
        "b2": {"temp": 21, "humidity": 42, "outdoor_temp": 15, "pm25": 22, "pmtovc": 28, "co2": 380},
        "a2": {"temp": 24, "humidity": 50, "outdoor_temp": 15, "pm25": 30, "pmtovc": 35, "co2": 450}
    },
    "valves": {
        "a1": {"room_temp": 22, "return_air_temp": 20, "fresh_air_temp": 18, "status": 0xFFFF},
        "b1": {"room_temp": 23, "return_air_temp": 21, "fresh_air_temp": 19, "status": 0xFFFF},
        "b2": {"room_temp": 21, "return_air_temp": 19, "fresh_air_temp": 17, "status": 0xFFFF},
        "a2": {"room_temp": 24, "return_air_temp": 22, "fresh_air_temp": 20, "status": 0xFFFF}
    },
    "is_energy_saving": False
}

# 系统日志
system_logs = []

def add_log(message):
    """添加系统日志"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = {
        "timestamp": timestamp,
        "message": message
    }
    system_logs.append(log_entry)
    if len(system_logs) > 100:  # 限制日志数量
        system_logs.pop(0)

def simulate_mvb_data():
    """模拟MVB数据更新"""
    while True:
        try:
            # 模拟温度变化
            for car in ['a1', 'b1', 'b2', 'a2']:
                train_data['temp_humi'][car]['temp'] += random.uniform(-1, 1)
                train_data['temp_humi'][car]['humidity'] += random.uniform(-2, 2)
                
                # 限制范围
                train_data['temp_humi'][car]['temp'] = max(15, min(30, train_data['temp_humi'][car]['temp']))
                train_data['temp_humi'][car]['humidity'] = max(30, min(70, train_data['temp_humi'][car]['humidity']))
            
            # 模拟重量变化
            for car in ['a1', 'b1', 'b2', 'a2']:
                train_data['weight'][car] += random.randint(-50, 50)
                train_data['weight'][car] = max(0, train_data['weight'][car])
            
            # 模拟能耗变化
            consumption_keys = ['driver_cab', 'a1', 'b1', 'b2', 'a2', 'tail_driver_cab']
            for key in consumption_keys:
                train_data['air_consumption'][key] += random.uniform(-0.1, 0.1)
                train_data['air_consumption'][key] = max(0, train_data['air_consumption'][key])
            
            # 重新计算总能耗
            train_data['air_consumption']['total'] = sum(
                train_data['air_consumption'][key] for key in consumption_keys
            )
            
            # 模拟阀门状态变化
            for car in ['a1', 'b1', 'b2', 'a2']:
                train_data['valves'][car]['status'] = random.randint(0, 0xFFFF)
                train_data['valves'][car]['room_temp'] += random.uniform(-0.5, 0.5)
                train_data['valves'][car]['return_air_temp'] += random.uniform(-0.5, 0.5)
                train_data['valves'][car]['fresh_air_temp'] += random.uniform(-0.5, 0.5)
                
                # 限制温度范围
                train_data['valves'][car]['room_temp'] = max(15, min(30, train_data['valves'][car]['room_temp']))
                train_data['valves'][car]['return_air_temp'] = max(15, min(30, train_data['valves'][car]['return_air_temp']))
                train_data['valves'][car]['fresh_air_temp'] = max(10, min(25, train_data['valves'][car]['fresh_air_temp']))
            
            # 模拟节能模式切换
            if random.random() < 0.05:  # 5%概率切换
                train_data['is_energy_saving'] = not train_data['is_energy_saving']
                add_log(f"节能模式切换: {'开启' if train_data['is_energy_saving'] else '关闭'}")
            
            # 更新时钟
            now = datetime.now()
            train_data['clock']['year'] = now.year
            train_data['clock']['month'] = now.month
            train_data['clock']['day'] = now.day
            train_data['clock']['hour'] = now.hour
            train_data['clock']['minute'] = now.minute
            train_data['clock']['second'] = now.second
            
            time.sleep(2)  # 每2秒更新一次
            
        except Exception as e:
            add_log(f"数据模拟错误: {str(e)}")
            time.sleep(5)

def start_mvb_simulation():
    """启动MVB数据模拟线程"""
    simulation_thread = threading.Thread(target=simulate_mvb_data, daemon=True)
    simulation_thread.start()
    add_log("MVB数据模拟已启动")

# API路由
@app.route('/')
def index():
    return send_from_directory('.', 'index.html')

@app.route('/api/train-data')
def get_train_data():
    """获取列车数据"""
    return jsonify(train_data)

@app.route('/api/logs')
def get_logs():
    """获取系统日志"""
    return jsonify(system_logs)

@app.route('/api/status')
def get_status():
    """获取系统状态"""
    total_weight = sum(train_data['weight'].values())
    total_consumption = train_data['air_consumption']['total']
    
    status = {
        "online": True,
        "last_update": datetime.now().isoformat(),
        "total_weight": total_weight,
        "total_consumption": total_consumption,
        "energy_saving": train_data['is_energy_saving'],
        "data_points": len(system_logs)
    }
    return jsonify(status)

@app.route('/api/control', methods=['POST'])
def control_action():
    """控制指令接口"""
    try:
        data = request.json
        action = data.get('action')
        target = data.get('target')
        value = data.get('value')
        
        if action == 'set_temperature':
            if target in train_data['valves']:
                train_data['valves'][target]['room_temp'] = value
                add_log(f"设置{target}车厢温度: {value}°C")
                return jsonify({"success": True, "message": f"温度设置成功: {value}°C"})
        
        elif action == 'toggle_energy_saving':
            train_data['is_energy_saving'] = not train_data['is_energy_saving']
            status = "开启" if train_data['is_energy_saving'] else "关闭"
            add_log(f"节能模式{status}")
            return jsonify({"success": True, "message": f"节能模式已{status}"})
        
        elif action == 'reset_valves':
            for car in train_data['valves']:
                train_data['valves'][car]['status'] = 0xFFFF
            add_log("所有阀门已重置为开启状态")
            return jsonify({"success": True, "message": "阀门重置成功"})
        
        return jsonify({"success": False, "message": "未知操作"})
        
    except Exception as e:
        add_log(f"控制指令错误: {str(e)}")
        return jsonify({"success": False, "message": str(e)})

@app.route('/api/export')
def export_data():
    """导出数据"""
    export_data = {
        "timestamp": datetime.now().isoformat(),
        "train_data": train_data,
        "logs": system_logs
    }
    return jsonify(export_data)

# 模拟UDP服务器（模拟MVB数据接收）
def start_udp_server():
    """启动UDP服务器模拟MVB数据接收"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('192.168.2.76', 9000))
        add_log("UDP服务器已启动，监听端口9000")
        
        while True:
            try:
                data, addr = sock.recvfrom(1024)
                # 模拟处理MVB数据
                add_log(f"收到来自 {addr} 的MVB数据: {len(data)} 字节")
                
                # 这里可以添加实际的数据解析逻辑
                # 模拟数据更新
                if len(data) >= 4:
                    port = struct.unpack('>H', data[2:4])[0]
                    add_log(f"端口 {port} 数据更新")
                
            except Exception as e:
                add_log(f"UDP接收错误: {str(e)}")
                
    except Exception as e:
        add_log(f"UDP服务器启动失败: {str(e)}")

def start_udp_simulation():
    """启动UDP服务器模拟线程"""
    udp_thread = threading.Thread(target=start_udp_server, daemon=True)
    udp_thread.start()

if __name__ == '__main__':
    # 启动数据模拟
    start_mvb_simulation()
    
    # 启动UDP服务器模拟
    start_udp_simulation()
    
    # 启动Flask应用
    add_log("列车数据监测系统已启动")
    app.run(host='0.0.0.0', port=5000, debug=True) 